package com.jketing.controller.spring.mvc.exception.handler;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import com.jketing.entity.ams.sys.Function;
import com.jketing.entity.ams.sys.Operation;
import com.jketing.service.ams.sys.FunctionService;
import com.jketing.service.ams.sys.OperationService;

/**
 * GlobalExceptionHandler 全局异常处理器
 * 
 * Spring-MVC 异常捕获方式
 * 1.在Controller中用@ExceptionHandler注解方法捕获异常,只在当前Controller中有效
 * 2.使用@ControllerAdvice注解全局异常捕获类，再在类中用@ExceptionHandler注解方法捕获异常,全局有效
 * 3.使用SimpleMappingExceptionResolver在Spring-MVC配置文件中来映射异常捕获,全局有效
 * 
 * @author  李荣华
 * @version v1.0
 * @date    2018-01-02
 * @since   Spring-mvc 4.3.8
 */
@ControllerAdvice
public class GlobalExceptionHandler {	
	/**
	 *  service 	服务层自动注入
	 */
	@Autowired
	private FunctionService functionService;
	/**
	 *  service 	服务层自动注入
	 */
	@Autowired
	private OperationService operationService;

	/**
	 *  handleUnauthorizedException 捕获UnauthorizedException异常方法 	
	 *  
	 *  Exception 有注解设置要捕获的异常
	 * 	 
	 *  @param 	Exception e 捕获的异常作为入参
	 *  
	 *  @return ModelAndView 必顺返回ModelAndView才能将异常带到jsp页面
	 */
	@ExceptionHandler({UnauthorizedException.class})
	public String handleUnauthorizedException(Exception e,HttpSession session){
		 
		String errorDescribe = "你没有<span style='color: red'>";
		String message = e.getLocalizedMessage();
		List<Function> funList = functionService.findByUseable("true");
		for(Function item:funList) {
			if("3".equals(item.getFunType())) {
				int index = message.indexOf(item.getStamp());
				if(index!=-1) {
					errorDescribe += item.getModuleName();
					break;
				}
			}
		}
		errorDescribe += "</span>模块的【<span style='color: red'>";
		List<Operation> list = operationService.findAll();
		for(Operation item:list) {
			int index = message.indexOf(item.getStamp());
			if(index!=-1) {
				errorDescribe += item.getName();
				break;
			}
		}
		errorDescribe += "</span>】权限,请联系系统管理员授与相关权限后再操作！";
		e.printStackTrace();
		session.setAttribute("errorDescribe", errorDescribe);
		return "redirect:/unauthorized";
	}
	
	/**
	 *  handleAuthorizationException 捕获AuthorizationException异常方法 	
	 *  
	 *  Exception 有注解设置要捕获的异常
	 * 	 
	 *  @param 	Exception e 捕获的异常作为入参
	 *  
	 *  @return ModelAndView 必顺返回ModelAndView才能将异常带到jsp页面
	 */
	@ExceptionHandler({AuthorizationException.class})
	public String handleAuthorizationException(Exception e,HttpSession session){
		 
		String errorDescribe = "你没有<span style='color: red'>";
		String message = e.getLocalizedMessage();
		List<Function> funList = functionService.findByUseable("true");
		for(Function item:funList) {
			if("3".equals(item.getFunType())) {
				int index = message.indexOf(item.getStamp());
				if(index!=-1) {
					errorDescribe += item.getModuleName();
					break;
				}
			}
		}
		errorDescribe += "</span>模块的【<span style='color: red'>";
		List<Operation> list = operationService.findAll();
		for(Operation item:list) {
			int index = message.indexOf(item.getStamp());
			if(index!=-1) {
				errorDescribe += item.getName();
				break;
			}
		}
		errorDescribe += "</span>】权限,请联系系统管理员授与相关权限后再操作！";
		e.printStackTrace();
		session.setAttribute("errorDescribe", errorDescribe);
		return "redirect:/unauthorized";
	}
	
	/**
	 *  handleException 捕获所有异常方法 	
	 * 	 
	 *  @param 	Exception e 捕获的异常作为入参
	 *  
	 *  @return String 
	 *  	1.必顺使用重定向返回,转发需要用ModelAndView,使用map页面收不到数据;tomcat8转发不了PUT和DELETE请求。
	 *  	2.因是使用重定向,数据写入session带回页面
	 */
	@ExceptionHandler({Exception.class})
	public String handleException(Exception e,HttpSession session){
		String errorCode=e.toString();
		String errorDescribe=e.getLocalizedMessage();
		String exceptionClass = "";
		String CausedBy="";
		String resolveWay="请将异常页截图发给管理员,并说明是进行那步操作出现的异常页！";
		String errorStackTrace = "";	
		Throwable tw = e.getCause();
		if(tw == null){
			CausedBy=e.getMessage();
			exceptionClass = e.getClass().getName();
		}
		else{
			Throwable tempTW = tw;
			while(tw != null){
				tw = tw.getCause();
				if(tw != null)
					tempTW = tw;
			}
			CausedBy=tempTW.getMessage();
			exceptionClass = tempTW.getClass().getName();
		}
		StringWriter sw = new StringWriter(); 
		PrintWriter pw = new PrintWriter(sw); 
		e.printStackTrace(pw); 
		e.printStackTrace();
		errorStackTrace = sw.toString();
		session.setAttribute("errorCode", errorCode);
		session.setAttribute("errorDescribe", errorDescribe);
		session.setAttribute("exceptionClass", exceptionClass);
		session.setAttribute("CausedBy", CausedBy);
		session.setAttribute("resolveWay", resolveWay);
		session.setAttribute("errorStackTrace", errorStackTrace.replaceAll( "\n", "<br/>"));
		return "redirect:exception";
	}
}
